﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace DBD.Common.Map
{
    public static class DataTableMap
    {
        /// <summary>
        /// DataTable 转换为IEnumerable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataTable"></param>
        /// <param name="refreshColumnNameParam">刷新列名(Key为模型属性，Value为Excel字段)</param>
        /// <returns></returns>
        public static IEnumerable<T> ToList<T>(this DataTable dataTable,
           Dictionary<string, string> refreshColumnNameParam = null) where T : new()
        {
            if (refreshColumnNameParam != null && dataTable.Columns.Count != refreshColumnNameParam.Count)
            {
                throw new ArgumentOutOfRangeException("refreshColumnNameParam", @"刷新列名与数据列不匹配");
            }

            Type type = typeof(T);

            PropertyInfo[] properties = type.GetProperties();

            List<T> list = new List<T>();

            foreach (DataRow row in dataTable.Rows)
            {
                T instance = Activator.CreateInstance<T>();
                foreach (PropertyInfo property in properties)
                {
                    string columnName = property.Name;
                    if (refreshColumnNameParam != null)
                    {
                        if (refreshColumnNameParam.ContainsKey(property.Name))
                            columnName = refreshColumnNameParam[property.Name];
                    }

                    if (row.Table.Columns.Contains(columnName))
                        property.SetValue(instance, row[columnName].ToPropertyInfoValue(property), null);
                }
                list.Add(instance);
            }
            return list;
        }


        // private

        /// <summary>
        /// 数据类型转换
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        private static object ToPropertyInfoValue(this object obj, PropertyInfo property)
        {
            if (property.PropertyType == obj.GetType())
                return obj;
            if (property.PropertyType == typeof(decimal))
            {
                return decimal.Parse(obj.ToString());
            }
            if (property.PropertyType == typeof(int))
            {
                return int.Parse(obj.ToString());
            }
            if (property.PropertyType == typeof(float))
            {
                return float.Parse(obj.ToString());
            }
            if (property.PropertyType == typeof(double))
            {
                return double.Parse(obj.ToString());
            }
            if (property.PropertyType == typeof(DateTime))
            {
                if (obj is DateTime)
                {
                    return obj;
                }
                return DateTime.Parse(obj.ToString());
            }
            return obj.ToString();
        }
    }
}
